package com.joolun.weixin.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joolun.common.corp.TenantContext;
import com.joolun.common.utils.DateUtils;
import com.joolun.common.utils.StringUtils;
import com.joolun.common.utils.uuid.IdUtils;
import com.joolun.system.domain.*;
import com.joolun.system.service.impl.SysCorpConfigServiceImpl;
import com.joolun.weixin.service.*;
import com.joolun.system.service.IEduSchedulingService;
import com.joolun.system.service.ISysConfigService;
import com.joolun.weixin.config.WxCpConfiguration;
import com.joolun.weixin.mapper.ScrmDeliveryPlanMapper;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 投放计划Service业务层处理
 * 
 * @author joolun
 * @date 2025-03-10
 */
@Service
@Slf4j
public class ScrmDeliveryPlanServiceImpl extends  ServiceImpl<ScrmDeliveryPlanMapper, ScrmDeliveryPlan> implements IScrmDeliveryPlanService
{
    @Autowired
    private ScrmDeliveryPlanMapper scrmDeliveryPlanMapper;

    @Autowired
    private IScrmPlanLinkService scrmPlanLinkService;

    @Autowired
    private IEduSchedulingService iEduSchedulingService;

    @Autowired
    private IEduSchedulingClassService iEduSchedulingClassService;

    @Autowired
    private IScrmJobUserService scrmJobUserService;

    @Autowired
    private ISysConfigService iSysConfigService;

    @Autowired
    private IScrmCustomerAcquisitionService iScrmCustomerAcquisitionService;

    @Autowired
    private IScrmCustomerInfoService iScrmCustomerInfoService;

    @Autowired
    private SysCorpConfigServiceImpl sysCorpConfigService;

    // 原子计数器，用于保证线程安全
    private static AtomicInteger currentIndex = new AtomicInteger(0);

    /**
     * 查询投放计划
     * 
     * @param id 投放计划主键
     * @return 投放计划
     */
    @Override
    public ScrmDeliveryPlan selectScrmDeliveryPlanById(Long id)
    {
        return scrmDeliveryPlanMapper.selectScrmDeliveryPlanById(id);
    }

    @Override
    public List<String> getWxContactCode(Long id,Long userId){
        List<String> result = new ArrayList<>();
        ScrmDeliveryPlan scrmDeliveryPlan = scrmDeliveryPlanMapper.selectScrmDeliveryPlanById(id);


        // 查找当前用户是否分配过企微员工
        ScrmCustomerInfo scrmCustomerInfo = iScrmCustomerInfoService.getById(userId);
        if(scrmCustomerInfo != null  && StringUtils.isNotEmpty(scrmCustomerInfo.getExtStaffId())){
            String staffId = scrmCustomerInfo.getExtStaffId();
            // 如果有加过企微员工则直接返回
            EduSchedulingClass eduSchedulingClass = iEduSchedulingClassService.getOne(Wrappers.lambdaQuery(EduSchedulingClass.class).eq(EduSchedulingClass::getWecomId,staffId));
            result.add(eduSchedulingClass.getQrCode());
            return result;
        }
        // 查找投放计划的课程排期信息
        Long courseId = scrmDeliveryPlan.getCourseId();
        // 查找课程查找排期计划里的所有符合当前时间的班级
        List<EduScheduling> eduSchedulingList = iEduSchedulingService.list(Wrappers.lambdaQuery(EduScheduling.class)
                .eq(EduScheduling::getCourseId, courseId)
                .lt(EduScheduling::getEnrollStartTime, DateUtils.getNowDate())
                .gt(EduScheduling::getEnrollEndTime, DateUtils.getNowDate())
                .orderByAsc(EduScheduling::getEnrollStartTime));
        log.info("--符合当前时间的课程排期:{}",eduSchedulingList.size());
        // 兜底二维码
        ScrmJobUser scrmJobUser = scrmJobUserService.getOne(Wrappers.lambdaQuery(ScrmJobUser.class).eq(ScrmJobUser::getCodeDefault,"1"));
        String qrCodeUrlDefault = "";
        try {
             qrCodeUrlDefault = scrmJobUser.getQrCode();
        }catch (Exception e){
            throw new RuntimeException("未设置兜底接量码！");
        }
        if(CollectionUtils.isEmpty(eduSchedulingList)){
            // 没有符合条件的排期则查找兜底码返回
            result.add(qrCodeUrlDefault);
            return result ;
        } else {
           // 排期的ids
            List<Long> ids = eduSchedulingList.stream().map(item ->item.getSchedulingId()).collect(Collectors.toList());
            // 查找排期的所有班级信息
            List<EduSchedulingClass> eduSchedulingClasseList = iEduSchedulingClassService.list(Wrappers.lambdaQuery(EduSchedulingClass.class).in(EduSchedulingClass::getSchedulingId,ids));
            // 正常接量,接量状态：1-正常接量，2-关闭接量
            eduSchedulingClasseList =  eduSchedulingClasseList.stream().filter(item->item.getReceivedQuantityStatus()==1).collect(Collectors.toList());
            // 排期没有班级也走兜底量
            if(CollectionUtils.isEmpty(eduSchedulingClasseList)){
                result.add(qrCodeUrlDefault);
               return result ;
            }

            //TODO:分配班级老师的多种方式,随机,轮询,权重,顺序
            EduScheduling eduScheduling = eduSchedulingList.get(0);
            Long schedulingId = eduScheduling.getSchedulingId();
            // 排期分班类型：1-顺序，2-随机，3-轮询
            Integer schedulingType = eduScheduling.getSchedulingType();
            log.info("-----排期分班类型1-顺序，2-随机，3-轮询:{}",schedulingType);
            // 根据排期和班级分组
            Map<Long, List<EduSchedulingClass>> resultListMap = eduSchedulingClasseList.stream().collect(Collectors.groupingBy(EduSchedulingClass::getSchedulingId));
            // 如果当前排期没有班级，则取下一次排期的班级
            String qrCodeUrl = "";
            EduSchedulingClass eduSchedulingClass = null;
            if(resultListMap.get(schedulingId) == null){
                List<EduSchedulingClass> eduSchedulingClasseCurrList = null;
                for (EduScheduling scheduling : eduSchedulingList) {
                    schedulingId = scheduling.getSchedulingId();
                    resultListMap = eduSchedulingClasseList.stream().collect(Collectors.groupingBy(EduSchedulingClass::getSchedulingId));
                    // 如果当前排期有班级，则采用
                    if (resultListMap.get(schedulingId) != null) {
                        eduSchedulingClasseCurrList = resultListMap.get(schedulingId);
                        break;
                    }
                }
                 //qrCodeUrl = checkResultQrCodeUrl(eduSchedulingClasseCurrList,schedulingType);
                eduSchedulingClass = checkResultEduSchedulingClass(eduSchedulingClasseCurrList,schedulingType);
            } else{
                // 当前排期的所有班级
                List<EduSchedulingClass> eduSchedulingClasseCurrList = resultListMap.get(schedulingId);
                // 获取二维码返回
                 //qrCodeUrl = checkResultQrCodeUrl(eduSchedulingClasseCurrList,schedulingType);
                eduSchedulingClass = checkResultEduSchedulingClass(eduSchedulingClasseCurrList,schedulingType);
            }
            result.add(eduSchedulingClass.getQrCode());
            // 绑定客户添加的企微员工
            if(scrmCustomerInfo != null){
                scrmCustomerInfo.setExtStaffId(eduSchedulingClass.getWecomId());
                iScrmCustomerInfoService.saveOrUpdate(scrmCustomerInfo);
            }
        }
        return result;
    }


    private String checkResultQrCodeUrl(List<EduSchedulingClass> eduSchedulingClasseCurrList ,Integer schedulingType){
        if(schedulingType == 3){
            // 轮询方式
            List<String> mentors = eduSchedulingClasseCurrList.stream().map(item->item.getQrCode()).collect(Collectors.toList());
            int index = currentIndex.getAndUpdate(i -> (i + 1) % mentors.size());
            String qrCodeUrl = mentors.get(index);
            return qrCodeUrl;
        }
        // iEduSchedulingClassService.list(Wrappers.lambdaQuery(EduSchedulingClass.class).eq(EduSchedulingClass::getSchedulingId,schedulingId).orderByDesc(EduSchedulingClass::getClassSort));
        Random random = new Random();
        int randomIndex = random.nextInt(eduSchedulingClasseCurrList.size());
        // 获取随机的EduSchedulingClass
        EduSchedulingClass randomClass = eduSchedulingClasseCurrList.get(randomIndex);
        String qrCodeUrl = randomClass.getQrCode();
        log.info("----:获取活码地址：{},自定义参数：{}",qrCodeUrl,randomClass.getState());
        return qrCodeUrl;
    }


    private EduSchedulingClass checkResultEduSchedulingClass(List<EduSchedulingClass> eduSchedulingClasseCurrList ,Integer schedulingType){
        if(schedulingType == 3){
            // 轮询方式
            int index = currentIndex.getAndUpdate(i -> (i + 1) % eduSchedulingClasseCurrList.size());
            EduSchedulingClass eduSchedulingClass = eduSchedulingClasseCurrList.get(index);
            return eduSchedulingClass;
        }
        // iEduSchedulingClassService.list(Wrappers.lambdaQuery(EduSchedulingClass.class).eq(EduSchedulingClass::getSchedulingId,schedulingId).orderByDesc(EduSchedulingClass::getClassSort));
        Random random = new Random();
        int randomIndex = random.nextInt(eduSchedulingClasseCurrList.size());
        // 获取随机的EduSchedulingClass
        EduSchedulingClass randomClass = eduSchedulingClasseCurrList.get(randomIndex);
        return randomClass;
    }


    /**
     * 查询投放计划列表
     * 
     * @param scrmDeliveryPlan 投放计划
     * @return 投放计划
     */
    @Override
    public List<ScrmDeliveryPlan> selectScrmDeliveryPlanList(ScrmDeliveryPlan scrmDeliveryPlan)
    {
        // 添加主体id
        scrmDeliveryPlan.setCorpId(TenantContext.getTenantId());
        return scrmDeliveryPlanMapper.selectScrmDeliveryPlanList(scrmDeliveryPlan);
    }

    /**
     * 新增投放计划
     * 
     * @param scrmDeliveryPlan 投放计划
     * @return 结果
     */
    @Override
    public int insertScrmDeliveryPlan(ScrmDeliveryPlan scrmDeliveryPlan)
    {
        // 添加主体id
        scrmDeliveryPlan.setCorpId(TenantContext.getTenantId());
        // tentative
        scrmDeliveryPlan.setExtCorpId(TenantContext.getTenantId());
        scrmDeliveryPlan.setCreateTime(DateUtils.getNowDate());
        scrmDeliveryPlanMapper.insertScrmDeliveryPlan(scrmDeliveryPlan);
        // TODO：微信外流程方式

        // 课程ID
        Long courseId = scrmDeliveryPlan.getCourseId();
        Integer processType = scrmDeliveryPlan.getProcessType();
        String planName = scrmDeliveryPlan.getPlanName();

        // 获取配置的跳转地址
        String configValue = iSysConfigService.selectConfigByKey("wx.forward.url");

        int linkCount = scrmDeliveryPlan.getLinkCount();

        // 获取投放计划的课程的班级员工账号
        Map<String, Object> map = getWxExtIdByPlanId(courseId);
        List<String> extIds = (List<String>)map.get("extList");
        log.info("---课程关联的员工账号信息：{}",extIds.toString());

        // 根据投放计划的课程排期查找关联微信生成链接
        List<ScrmPlanLink> scrmPlanLinkAddList = new ArrayList<>();
        for(int i = 0;i < linkCount;i++){
            ScrmPlanLink scrmPlanLink = new ScrmPlanLink();
            scrmPlanLink.setPlanId(scrmDeliveryPlan.getId());
            String linkCode = IdUtils.generateRandomKey(8);
            scrmPlanLink.setUrlLink(configValue + linkCode);
            scrmPlanLink.setName(planName);
            scrmPlanLink.setShortCode(linkCode);
            scrmPlanLinkAddList.add(scrmPlanLink);
        }
        scrmPlanLinkService.saveBatch(scrmPlanLinkAddList);
        // 获取助手
        if(processType > 3){
            // 创建获客助手之前先判断当前课程是否已存在，如果不存在再创建
            ScrmCustomerAcquisition customerAcquisition = iScrmCustomerAcquisitionService.getOne(Wrappers.lambdaQuery(ScrmCustomerAcquisition.class).eq(ScrmCustomerAcquisition::getCourseId,courseId));
            if(customerAcquisition == null){
                // 新增获客助手
                ScrmCustomerAcquisition scrmCustomerAcquisition = new ScrmCustomerAcquisition();
                // 调用企微创建获客助手链接
                String createLinkResult = this.createLink(planName + "_"+scrmDeliveryPlan.getId(),extIds);
                JSONObject jsonObject = JSONObject.parseObject(createLinkResult);
                int code = jsonObject.getInteger("errcode");
                if(code == 0 ){
                    String link = jsonObject.getString("link");
                    JSONObject linkJson = JSONObject.parseObject(link);
                    String linkId = linkJson.getString("link_id");
                    String url = linkJson.getString("url");
                    // 获取排期id
                    String schedulingId = map.get("schedulingId").toString();
                    scrmCustomerAcquisition.setSchedulingId(schedulingId);
                    scrmCustomerAcquisition.setConfigId(linkId);
                    scrmCustomerAcquisition.setCourseId(courseId);
                    scrmCustomerAcquisition.setExtId(extIds.toString());
                    scrmCustomerAcquisition.setLinkUrl(url);
                    scrmCustomerAcquisition.setStatus(1);
                    scrmCustomerAcquisition.setLinkName(planName + "_"+scrmDeliveryPlan.getId());
                    scrmCustomerAcquisition.setCreateTime(DateUtils.getNowDate());
                    scrmCustomerAcquisition.setExtCorpId(TenantContext.getTenantId());
                    scrmCustomerAcquisition.setCreateTime(DateUtils.getNowDate());
                    // 更新获客助手时间
                    scrmCustomerAcquisition.setUpdateTime(DateUtils.getNowDate());
                    // 主体id，区分链接
                    scrmCustomerAcquisition.setCorpId(TenantContext.getTenantId());
                    iScrmCustomerAcquisitionService.save(scrmCustomerAcquisition);
                }
            }
        }

        return 1;
    }


    /**
     * 根据投放计划Id查找配置的企微员工
     * @param courseId 课程ID
     * @return
     */
    public Map<String, Object> getWxExtIdByPlanId(Long courseId){
        Map<String, Object> map = new HashMap<>();
        List<String> result = new ArrayList<>();

        // 查找课程查找排期计划里的所有符合当前时间的班级
        List<EduScheduling> eduSchedulingList = iEduSchedulingService.list(Wrappers.lambdaQuery(EduScheduling.class)
                .eq(EduScheduling::getCourseId, courseId)
                .lt(EduScheduling::getEnrollStartTime, DateUtils.getNowDate())
                .gt(EduScheduling::getEnrollEndTime, DateUtils.getNowDate())
                .orderByAsc(EduScheduling::getEnrollStartTime));
        log.info("--符合当前时间的课程排期:{}",eduSchedulingList.size());

        // 兜底二维码
        ScrmJobUser scrmJobUser = scrmJobUserService.getOne(Wrappers.lambdaQuery(ScrmJobUser.class)
                .eq(ScrmJobUser::getCodeDefault,"1").eq(ScrmJobUser::getCorpId,TenantContext.getTenantId()));
        String extId = "";
        if(scrmJobUser != null){
            extId = scrmJobUser.getExtId();
        }else{
            throw new RuntimeException("未设置兜底接量码，创建投放计划前请先设置兜底接量码");
        }
        if(CollectionUtils.isEmpty(eduSchedulingList)){
            throw new RuntimeException("未设置接量排期，请先设置接量排期");
        } else {
            // 排期的ids
            List<Long> ids = eduSchedulingList.stream().map(item ->item.getSchedulingId()).collect(Collectors.toList());
            // 查找排期的所有班级信息
            List<EduSchedulingClass> eduSchedulingClasseList = iEduSchedulingClassService.list(Wrappers.lambdaQuery(EduSchedulingClass.class).in(EduSchedulingClass::getSchedulingId,ids));
            // 正常接量
            eduSchedulingClasseList =  eduSchedulingClasseList.stream().filter(item->item.getReceivedQuantityStatus()==1).collect(Collectors.toList());
            // 排期没有班级也走兜底量
            if(CollectionUtils.isEmpty(eduSchedulingClasseList)){
                result.add(extId);
                // 设置第一个排期的id为进量排期
                map.put("schedulingId", eduSchedulingList.get(0).getSchedulingId());
                map.put("extList", result);
                return map;
            }
            // 获取有效排期，如果当期没有则取下一期
            Map<String, Object> mapClass = getEduSchedulingClasseCurrList(eduSchedulingList,eduSchedulingClasseList);
            List<EduSchedulingClass> listClass = (List<EduSchedulingClass>)mapClass.get("eduSchedulingClasseCurrList");
            List<String> extIdsByClass = listClass.stream().map(item->item.getWecomId()).collect(Collectors.toList());
            map.put("schedulingId", mapClass.get("schedulingId"));
//            List<String> extIdsByClass = eduSchedulingClasseCurrList.stream().map(item->item.getWecomId()).collect(Collectors.toList());
            map.put("extList", extIdsByClass);
        }
        return map;
    }


    /**
     * 创建获客助手链接
     * @param name
     * @param extIds
     * @return
     */
    private String createLink(String name,List<String> extIds){
        String createLinkResult = "";
        // 获取主体配置
        SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
        WxCpService wxCpService = WxCpConfiguration.getWxCpService(sysCorpConfig);

        try {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("link_name",name);
            //resultMap.put("state", state); // 传入自定义的state
            Map<String, Object> rangeMap = new HashMap<>();
            rangeMap.put("user_list", extIds);
            resultMap.put("range", rangeMap);
            resultMap.put("skip_verify", true);

            createLinkResult = wxCpService.post("https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_acquisition/create_link", JSONObject.toJSONString(resultMap));
            log.info("----创建获客链接接口返回:{}",createLinkResult);
            //----创建获客链接接口返回:{"errcode":0,"errmsg":"ok","link":{"link_id":"cawcded4d1bb1d8904","link_name":"获客链接17号","url":"https://work.weixin.qq.com/ca/cawcded4d1bb1d8904","create_time":1742283206}}
        } catch (WxErrorException e) {
            log.error("--调用企微创建获客助手接口异常：{}",e.getMessage());
            throw new RuntimeException(e);
        }
        return createLinkResult;
    }
    /**
     * 查找排期的当前班级，如果没有则取下一个排期
     * @param eduSchedulingList
     * @param eduSchedulingClasseList
     * @return
     */
    private Map<String, Object> getEduSchedulingClasseCurrList(List<EduScheduling> eduSchedulingList,List<EduSchedulingClass> eduSchedulingClasseList){
        Map<String, Object> map = new HashMap<>();
        Map<Long, List<EduSchedulingClass>> resultListMap = eduSchedulingClasseList.stream().collect(Collectors.groupingBy(EduSchedulingClass::getSchedulingId));
        // 如果当前排期没有班级，则取下一次排期的班级
        List<EduSchedulingClass> eduSchedulingClasseCurrList = null;
        for (EduScheduling scheduling : eduSchedulingList) {
            Long schedulingId = scheduling.getSchedulingId();
            //resultListMap = eduSchedulingClasseList.stream().collect(Collectors.groupingBy(EduSchedulingClass::getSchedulingId));
            // 如果当前排期有班级，则采用
            if (resultListMap.get(schedulingId) != null) {
                eduSchedulingClasseCurrList = resultListMap.get(schedulingId);
                map.put("schedulingId", schedulingId);
                map.put("eduSchedulingClasseCurrList", eduSchedulingClasseCurrList);
                break;
            }
        }
        return map;
    }

    /**
     * 修改投放计划
     * 
     * @param scrmDeliveryPlan 投放计划
     * @return 结果
     */
    @Override
    public int updateScrmDeliveryPlan(ScrmDeliveryPlan scrmDeliveryPlan) {
        scrmDeliveryPlan.setUpdateTime(DateUtils.getNowDate());

        // 课程ID
        Long courseId = scrmDeliveryPlan.getCourseId();
        Integer processType = scrmDeliveryPlan.getProcessType();
        String planName = scrmDeliveryPlan.getPlanName();

        //修改获客助手,由原来没有获客链接的改为配置4，5方式
        if(processType > 3){
            // 获取投放计划的课程的班级员工账号
            Map<String, Object> map = getWxExtIdByPlanId(courseId);
            List<String> extIds = (List<String>)map.get("extList");
            log.info("---课程关联的员工账号信息：{}",extIds.toString());
            // 查询该课程是否有获客链接
            ScrmCustomerAcquisition scrmCustomerAcquisitionTest = iScrmCustomerAcquisitionService.getOne(Wrappers.lambdaQuery(ScrmCustomerAcquisition.class)
                    .eq(ScrmCustomerAcquisition::getCourseId,courseId));
            if(scrmCustomerAcquisitionTest == null){
                ScrmCustomerAcquisition scrmCustomerAcquisition = new ScrmCustomerAcquisition();
                // 调用企微创建获客助手链接
                String linkName = planName + "_"+scrmDeliveryPlan.getId();
                String createLinkResult = this.createLink(linkName,extIds);
                JSONObject jsonObject = JSONObject.parseObject(createLinkResult);
                int code = jsonObject.getInteger("errcode");
                if(code == 0 ){
                    // 获取排期id
                    String schedulingId = map.get("schedulingId").toString();
                    scrmCustomerAcquisition.setSchedulingId(schedulingId);
                    String link = jsonObject.getString("link");
                    JSONObject linkJson = JSONObject.parseObject(link);
                    String linkId = linkJson.getString("link_id");
                    String url = linkJson.getString("url");

                    scrmCustomerAcquisition.setConfigId(linkId);
                    scrmCustomerAcquisition.setCourseId(courseId);
                    scrmCustomerAcquisition.setExtId(extIds.toString());
                    scrmCustomerAcquisition.setLinkUrl(url);
                    scrmCustomerAcquisition.setStatus(1);
                    scrmCustomerAcquisition.setCreateTime(DateUtils.getNowDate());
                    // 更新获客助手时间
                    scrmCustomerAcquisition.setUpdateTime(DateUtils.getNowDate());
                    scrmCustomerAcquisition.setRemark(linkName);
                    scrmCustomerAcquisition.setCorpId(TenantContext.getTenantId());
                    scrmCustomerAcquisition.setExtCorpId(TenantContext.getTenantId());
                    iScrmCustomerAcquisitionService.save(scrmCustomerAcquisition);
                }
            }
        }
        return scrmDeliveryPlanMapper.updateScrmDeliveryPlan(scrmDeliveryPlan);
    }

    /**
     * 批量删除投放计划
     * 
     * @param ids 需要删除的投放计划主键
     * @return 结果
     */
    @Override
    public int deleteScrmDeliveryPlanByIds(Long[] ids)
    {
        return scrmDeliveryPlanMapper.deleteScrmDeliveryPlanByIds(ids);
    }

    /**
     * 删除投放计划信息
     * 
     * @param id 投放计划主键
     * @return 结果
     */
    @Override
    public int deleteScrmDeliveryPlanById(Long id)
    {
        return scrmDeliveryPlanMapper.deleteScrmDeliveryPlanById(id);
    }
}
